﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace mrp16062010.Uretec
{
    class UrunAgaciUret
    {
        /*private static UrunAgaciUret nesne;
        private static object syncRoot = new Object();

        c

        

        public static UrunAgaciUret Nesne
        {
            get
            {
                if (nesne == null)
                {
                    lock (syncRoot)
                    {
                        if (nesne == null)
                            nesne = new UrunAgaciUret();
                    }
                }
                return nesne;
            }
        }*/

        public List<Rota.RotaParcasi> ListeUret(UrunAgaciTipi tip, int adet)
        {
            List<Rota.RotaParcasi> parcaList = new List<Rota.RotaParcasi>();

            for (int i = 0; i < adet; i++)
            {
                Rota.RotaParcasi rndParca = Uret(tip, i);
                //foreach (var parca in rndParca.OperasyonList.First().AltParca)
                //{
                //    if (parca.Tanim.Contains("Montaj"))
                //{
                    
                //}
                //}
                
                parcaList.Add(rndParca);
            }
            EsitDagit(parcaList);
            return parcaList;
        }

        public Rota.RotaParcasi Uret(UrunAgaciTipi tip, int kod)
        {
            rndImalatBilesenAdet.Beta = tip.BilesenKullanimAdediImalat.Max;
            rndImalatBilesenAdet.Alpha = tip.BilesenKullanimAdediImalat.Min;
            rndMontajBilesenAdet.Beta = tip.BilesenKullanimAdediMontaj.Max;
            rndMontajBilesenAdet.Alpha = tip.BilesenKullanimAdediMontaj.Min;
            rndImalParcaAdet.Beta = tip.SayiImalEdilen.Max;
            rndImalParcaAdet.Alpha = tip.SayiImalEdilen.Min;
            rndAltUrunAdet.Beta = tip.SayiAltUrun.Max;
            rndAltUrunAdet.Alpha = tip.SayiAltUrun.Min;
            rndImOpAdet.Beta = tip.ImalatOperasyonSayisi.Max;
            rndImOpAdet.Alpha = tip.ImalatOperasyonSayisi.Min;
            rndMontajOpAdet.Beta = tip.MontajOperasyonSayisi.Max;
            rndMontajOpAdet.Alpha = tip.MontajOperasyonSayisi.Min;
            rndImalatHazirlikSuresi.Beta = tip.ImalatHazirlikSuresi.Max;
            rndImalatHazirlikSuresi.Alpha = tip.ImalatHazirlikSuresi.Min;
            rndImalatOperasyonSuresi.Beta = tip.ImalatOperasyonSuresi.Max;
            rndImalatOperasyonSuresi.Alpha = tip.ImalatOperasyonSuresi.Min;
            rndMontajHazirlikSuresi.Beta = tip.MontajHazirlikSuresi.Max;
            rndMontajHazirlikSuresi.Alpha = tip.MontajHazirlikSuresi.Min;
            rndMontajOperasyonSuresi.Beta = tip.MontajOperasyonSuresi.Max;
            rndMontajOperasyonSuresi.Alpha = tip.MontajOperasyonSuresi.Min;
            rndImIsMerkezi.Beta = 18;
            rndImIsMerkezi.Alpha = 7;
            rndMontajIsMerkezi.Beta = 6;
            rndMontajIsMerkezi.Alpha = 1;


            Mamul mamul = new Mamul();
            mamul.Ad = "Kök "+kod.ToString();
            mamul.Kod = kod;
            Rota.RotaParcasi kokParca = new Rota.RotaParcasi(mamul, 1);
            kokParca.Tanim = "Kök " + kod.ToString();
            kokParca.StokKodu = kod;
            kokParca.Kod = kod;
            //Kök için operasyon üret
            int montakOpAdet=rndMontajOpAdet.Next();
            for (int j = 0; j < montakOpAdet; j++)
            {
                //iş merkezleri arasından (veritabanından) x. merkezi rnd seç
                IsMerkezi merkez = OrnekVeri.IsMerkeziList[rndMontajIsMerkezi.Next() - 1];
                TimeSpan opSure = new TimeSpan(0, rndMontajOperasyonSuresi.Next(), 0);
                TimeSpan hazSure = new TimeSpan(0, rndMontajHazirlikSuresi.Next(), 0);
                Rota.Operasyon operasyon = new Rota.Operasyon(j, j.ToString(), opSure, hazSure, merkez);
                operasyon.Turu = Rota.Operasyon.Tur.Montaj;
                kokParca.OperasyonEkle(operasyon);
            }

            StokParcaUret(kokParca, mamul, rndImalParcaAdet.Next(), rndAltUrunAdet.Next(), tip.Seviye, tip);
            return kokParca;
        }

        Troschuetz.Random.DiscreteUniformDistribution rndImalParcaAdet = new Troschuetz.Random.DiscreteUniformDistribution();
        Troschuetz.Random.DiscreteUniformDistribution rndAltUrunAdet = new Troschuetz.Random.DiscreteUniformDistribution();
        Troschuetz.Random.DiscreteUniformDistribution rndMontajBilesenAdet = new Troschuetz.Random.DiscreteUniformDistribution();
        Troschuetz.Random.DiscreteUniformDistribution rndImalatBilesenAdet = new Troschuetz.Random.DiscreteUniformDistribution();
        Troschuetz.Random.DiscreteUniformDistribution rndImOpAdet = new Troschuetz.Random.DiscreteUniformDistribution();
        Troschuetz.Random.DiscreteUniformDistribution rndMontajOpAdet = new Troschuetz.Random.DiscreteUniformDistribution();
        Troschuetz.Random.DiscreteUniformDistribution rndImIsMerkezi = new Troschuetz.Random.DiscreteUniformDistribution();
        Troschuetz.Random.DiscreteUniformDistribution rndMontajIsMerkezi = new Troschuetz.Random.DiscreteUniformDistribution();
        Troschuetz.Random.DiscreteUniformDistribution rndImalatHazirlikSuresi = new Troschuetz.Random.DiscreteUniformDistribution();
        Troschuetz.Random.DiscreteUniformDistribution rndImalatOperasyonSuresi = new Troschuetz.Random.DiscreteUniformDistribution();
        Troschuetz.Random.DiscreteUniformDistribution rndMontajHazirlikSuresi = new Troschuetz.Random.DiscreteUniformDistribution();
        Troschuetz.Random.DiscreteUniformDistribution rndMontajOperasyonSuresi = new Troschuetz.Random.DiscreteUniformDistribution();
        
        private void StokParcaUret(Rota.RotaParcasi rotaGelen, Stok stokGelen, int imalatParcaAdet, int montajParcaAdet , int Limit, UrunAgaciTipi tip)//direk tipten limmiti al
        {
            int gelenSeviye = rotaGelen.Seviye();
            if (gelenSeviye < Limit)
            {
                //Yarı ürün (Montaj) üretici
                for (int i = 0; i < montajParcaAdet; i++)
                {
                    YariMamul parca = new YariMamul();
                    parca.Ad = i.ToString();

                    parca.Adet = rndMontajBilesenAdet.Next();
                    stokGelen.Ekle(parca);
                    //yanlış gelen.BilesenList.Add(parca);
                    /*Rota Parçası Oluşturuyoruz*/
                    Rota.RotaParcasi rotaParcasi = new Rota.RotaParcasi(parca, parca.Adet);
                    rotaParcasi.Tanim = "Montaj "+(rotaGelen.Seviye() + 1).ToString();
                    rotaGelen.OperasyonList.First().RotaParcasiEkle(rotaParcasi);

                    //Rotaya operasyon oluşturuyoruz
                    int montOpAdet = rndMontajOpAdet.Next();
                    for (int j = 0; j < montOpAdet; j++)
                    {
                        //iş merkezleri arasından (veritabanından) x. merkezi rnd seç
                        int rasIsMerkezi = rndMontajIsMerkezi.Next();
                        IsMerkezi merkez = OrnekVeri.IsMerkeziList[rasIsMerkezi - 1];
                        TimeSpan opSure = new TimeSpan(0, rndMontajOperasyonSuresi.Next(), 0);
                        TimeSpan hazSure = new TimeSpan(0, rndMontajHazirlikSuresi.Next(), 0);
                        Rota.Operasyon operasyon = new Rota.Operasyon(j, j.ToString(), opSure, hazSure, merkez);
                        operasyon.Turu = Rota.Operasyon.Tur.Montaj;
                        rotaParcasi.OperasyonEkle(operasyon);
                    }
                    //Bu son operasyona eklenecek olan rota parçası ve stokları burada oluştur ve StokParcaUrete at
                    if (rotaGelen.Seviye() == tip.Seviye-3)
                    {
                        //Imal edilen bir parça ile kapat
                        StokParcaUret(rotaParcasi, parca, 2, 0, Limit, tip);
                    }
                    else
                    {
                        StokParcaUret(rotaParcasi, parca, rndImalParcaAdet.Next(), rndAltUrunAdet.Next(), Limit, tip);
                    }
                    
                }

                //İmalat için üretici
                for (int i = 0; i < imalatParcaAdet; i++)
                {
                    ImalEdilenParcaUret(stokGelen, rotaGelen, i);
                }
            }
            else
            {
                return;
            }
        }

        private void ImalEdilenParcaUret(Stok stokGelen, Rota.RotaParcasi rotaGelen, int i)
        {
            YariMamul parca = new YariMamul();
            parca.Ad = i.ToString();
            parca.Adet = rndImalatBilesenAdet.Next();
            stokGelen.Ekle(parca);
            //yanlış gelen.BilesenList.Add(parca);
            /*Rota Parçası Oluşturuyoruz*/
            Rota.RotaParcasi rotaParcasi = new Rota.RotaParcasi(parca, parca.Adet);
            rotaParcasi.Tanim = "İmalat " + (rotaGelen.Seviye() + 1).ToString();
            rotaGelen.OperasyonList.First().RotaParcasiEkle(rotaParcasi);
            //Rotaya operasyon oluşturuyoruz

            int rasImOpAdet = rndImOpAdet.Next();
            for (int j = 0; j < rasImOpAdet; j++)
            {
                //iş merkezleri arasından (veritabanından) x. merkezi rnd seç
                int rndMerkezSayisi = rndImIsMerkezi.Next() - 1;
                IsMerkezi merkez = OrnekVeri.IsMerkeziList[rndMerkezSayisi];
                TimeSpan opSure = new TimeSpan(0, rndImalatOperasyonSuresi.Next(), 0);
                TimeSpan hazSure = new TimeSpan(0, rndImalatHazirlikSuresi.Next(), 0);
                Rota.Operasyon operasyon = new Rota.Operasyon(j, j.ToString(), opSure, hazSure, merkez);
                operasyon.Turu = Rota.Operasyon.Tur.Imalat;
                rotaParcasi.OperasyonEkle(operasyon);
            }


            /*En sonuncu operasyondan sonra hammadde ekle ve kapat*/
            YariMamul hammadde = new YariMamul();
            hammadde.Ad = i.ToString();
            hammadde.Kod = i;
            parca.Ekle(hammadde);
            Rota.RotaParcasi hammaddeRotaParca = new Rota.RotaParcasi(hammadde, 1);
            hammaddeRotaParca.Tanim = "İmalat Hammadde " + (rotaGelen.Seviye() + 1).ToString();
            rotaParcasi.OperasyonList.First().RotaParcasiEkle(hammaddeRotaParca);
            //StokParcaUret(parca, rndAltUrunAdet.Next(), Limit, tip);
        }

        public void EsitDagit(List<Rota.RotaParcasi> parcalar)
        {
            foreach (IsMerkezi merkez in OrnekVeri.IsMerkeziList)
            {
                merkez.Yuk = 0;
            }
            //OrnekVeri.IsMerkeziList
            foreach (Rota.RotaParcasi parca in parcalar)
            {
                OperasyonGez(parca);
            }

            foreach (IsMerkezi merkez in OrnekVeri.IsMerkeziList)
            {
                merkez.Yuk = 0;
            }
        }

        private void OperasyonGez(Rota.RotaParcasi parca)
        {
            List<IsMerkezi> secilenlerMontaj = new List<IsMerkezi>();
            List<IsMerkezi> secilenlerImalat = new List<IsMerkezi>();
            foreach (Rota.Operasyon op in parca.OperasyonList.Reverse<Rota.Operasyon>())
            {
                if (op.AltParca.FirstOrDefault() == null)
                {
                    //operasyonun altına bağlı bi dal yoksa
                    //operasyonu makineye ata
                    
                    IEnumerable<IsMerkezi> eldekiMontaj = OrnekVeri.IsMerkeziList.Where(x => x.UretimTuru == Rota.Operasyon.Tur.Montaj).Except(secilenlerMontaj);
                    int minYukMontaj = eldekiMontaj.Min(x => x.Yuk);
                    IEnumerable<IsMerkezi> merkezlerMontaj = eldekiMontaj.Where(x => x.Yuk == minYukMontaj);

                    
                    IEnumerable<IsMerkezi> eldekiImalat = OrnekVeri.IsMerkeziList.Where(x => x.UretimTuru == Rota.Operasyon.Tur.Imalat).Except(secilenlerImalat);
                    int minYukImalat = eldekiImalat.Min(x => x.Yuk);
                    IEnumerable<IsMerkezi> merkezlerImalat = eldekiImalat.Where(x => x.Yuk == minYukImalat);

                    IEnumerable<IsMerkezi> secilecekler;

                    if (op.Turu == Rota.Operasyon.Tur.Montaj)
                    {
                        secilecekler = merkezlerMontaj;
                    }
                    else
                    {
                        secilecekler = merkezlerImalat;
                    }
                    Random rand = new Random();
                    IsMerkezi secilen = secilecekler.ElementAt(rand.Next(secilecekler.Count()));
                    secilen.Yuk++;
                    op.IsMerkeziRota = secilen;

                    if (op.Turu == Rota.Operasyon.Tur.Montaj)
                    {
                        secilenlerMontaj.Add(secilen);
                    }
                    else
                    {
                        secilenlerImalat.Add(secilen);
                    }
                }
                else
                {
                    //operasyonun altına bağlı bi dal varsa
                    foreach (Rota.RotaParcasi alttakiParca in op.AltParca)
                    {
                        OperasyonGez(alttakiParca);
                    }
                }
            }
        }
        /*
        public Rota.RotaParcasi Uret(int maxSeviye, int maxParca, int maxOperasyon)
        {
            return new Rota.RotaParcasi(
        }*/
    }
}
